package config

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/spf13/viper"
)

// Config 应用配置结构
type Config struct {
	App      AppConfig      `mapstructure:"app"`
	Database DatabaseConfig `mapstructure:"database"`
	GRPC     GRPCConfig     `mapstructure:"grpc"`
	HTTP     HTTPConfig     `mapstructure:"http"`
	Etcd     EtcdConfig     `mapstructure:"etcd"`
}

// AppConfig 应用基础配置
type AppConfig struct {
	Name        string `mapstructure:"name"`
	Version     string `mapstructure:"version"`
	Environment string `mapstructure:"environment"`
	LogLevel    string `mapstructure:"log_level"`
}

// DatabaseConfig 数据库配置
type DatabaseConfig struct {
	Host            string `mapstructure:"host"`
	Port            int    `mapstructure:"port"`
	User            string `mapstructure:"user"`
	Password        string `mapstructure:"password"`
	Database        string `mapstructure:"database"`
	MaxOpenConns    int    `mapstructure:"max_open_conns"`
	MaxIdleConns    int    `mapstructure:"max_idle_conns"`
	ConnMaxLifetime int    `mapstructure:"conn_max_lifetime"` // 分钟
}

// GRPCConfig gRPC 服务配置
type GRPCConfig struct {
	Port int `mapstructure:"port"`
}

// HTTPConfig HTTP 服务配置
type HTTPConfig struct {
	Port int `mapstructure:"port"`
}

// EtcdConfig etcd 配置
type EtcdConfig struct {
	Endpoints []string `mapstructure:"endpoints"`
	Timeout   int      `mapstructure:"timeout"` // 秒
}

var globalConfig *Config

// LoadConfig 加载配置文件
func LoadConfig(configPath string) (*Config, error) {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	
	// 设置配置文件搜索路径
	if configPath != "" {
		viper.AddConfigPath(configPath)
	}
	viper.AddConfigPath("./configs")
	viper.AddConfigPath("./config")
	viper.AddConfigPath(".")
	
	// 设置环境变量前缀
	viper.SetEnvPrefix("LEARN_GO_DEMO")
	viper.AutomaticEnv()
	
	// 设置默认值
	setDefaults()
	
	// 读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			log.Printf("配置文件未找到，使用默认配置")
		} else {
			return nil, fmt.Errorf("读取配置文件失败: %w", err)
		}
	} else {
		log.Printf("使用配置文件: %s", viper.ConfigFileUsed())
	}
	
	var config Config
	if err := viper.Unmarshal(&config); err != nil {
		return nil, fmt.Errorf("解析配置失败: %w", err)
	}
	
	// 从环境变量覆盖敏感配置
	overrideFromEnv(&config)
	
	globalConfig = &config
	return &config, nil
}

// setDefaults 设置默认配置值
func setDefaults() {
	// 应用配置
	viper.SetDefault("app.name", "learn-go-demo")
	viper.SetDefault("app.version", "1.0.0")
	viper.SetDefault("app.environment", "development")
	viper.SetDefault("app.log_level", "info")
	
	// 数据库配置
	viper.SetDefault("database.host", "localhost")
	viper.SetDefault("database.port", 3306)
	viper.SetDefault("database.user", "root")
	viper.SetDefault("database.password", "password")
	viper.SetDefault("database.database", "learn_go_demo")
	viper.SetDefault("database.max_open_conns", 25)
	viper.SetDefault("database.max_idle_conns", 25)
	viper.SetDefault("database.conn_max_lifetime", 5)
	
	// gRPC 配置
	viper.SetDefault("grpc.port", 50051)
	
	// HTTP 配置
	viper.SetDefault("http.port", 8081)
	
	// etcd 配置
	viper.SetDefault("etcd.endpoints", []string{"localhost:2379"})
	viper.SetDefault("etcd.timeout", 5)
}

// overrideFromEnv 从环境变量覆盖敏感配置
func overrideFromEnv(config *Config) {
	if dbHost := os.Getenv("DB_HOST"); dbHost != "" {
		config.Database.Host = dbHost
	}
	if dbPort := os.Getenv("DB_PORT"); dbPort != "" {
		viper.Set("database.port", dbPort)
		config.Database.Port = viper.GetInt("database.port")
	}
	if dbUser := os.Getenv("DB_USER"); dbUser != "" {
		config.Database.User = dbUser
	}
	if dbPassword := os.Getenv("DB_PASSWORD"); dbPassword != "" {
		config.Database.Password = dbPassword
	}
	if dbName := os.Getenv("DB_NAME"); dbName != "" {
		config.Database.Database = dbName
	}
}

// GetConfig 获取全局配置
func GetConfig() *Config {
	if globalConfig == nil {
		log.Fatal("配置未初始化，请先调用 LoadConfig")
	}
	return globalConfig
}

// GetDatabaseConfig 获取数据库配置
func GetDatabaseConfig() DatabaseConfig {
	return GetConfig().Database
}

// CreateConfigFile 创建示例配置文件
func CreateConfigFile(path string) error {
	configDir := filepath.Dir(path)
	if err := os.MkdirAll(configDir, 0755); err != nil {
		return fmt.Errorf("创建配置目录失败: %w", err)
	}
	
	exampleConfig := `# Learn Go Demo 配置文件

app:
  name: "learn-go-demo"
  version: "1.0.0"
  environment: "development"  # development, production, test
  log_level: "info"          # debug, info, warn, error

database:
  host: "localhost"
  port: 3306
  user: "root"
  password: "password"
  database: "learn_go_demo"
  max_open_conns: 25
  max_idle_conns: 25
  conn_max_lifetime: 5  # 分钟

grpc:
  port: 50051

http:
  port: 8081

etcd:
  endpoints:
    - "localhost:2379"
  timeout: 5  # 秒

# 注意：敏感信息可以通过环境变量覆盖：
# DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME
`
	
	return os.WriteFile(path, []byte(exampleConfig), 0644)
}
